<?php
// +----------------------------------------------------------------------
// | B5Yii2CMF V3.0 [快捷通用基础管理开发平台]
// +----------------------------------------------------------------------
// | Author: 冰舞 <357145480@qq.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace common\helpers;

use common\extend\exception\ErrorCode;
use common\extend\exception\B5HttpException;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use yii\helpers\ArrayHelper;

class ExportHelper
{
    protected array $list = [];
    protected array $row = [];
    protected string $fileName = '';
    protected array $widthList = [];
    protected array $boldList = [];
    protected array $sizeList = [];
    protected array $fontList = [];
    protected array $wrapList = [];
    protected array $colorList = [];
    protected array $backgroundList = [];
    public bool $saveFile = true; //保存文件 还是 直接浏览器下载

    public function __construct(array $data)
    {
        $this->list = isset($data['list']) ? $data['list'] : [];
        $this->row = isset($data['row']) ? $data['row'] : [];
        $this->fileName = $data['fileName'] ?? '';
        $this->setWidthList($data['width']??[]);
        $this->setBoldList($data['bold']??[]);
        $this->setSizeList($data['size']??[]);
        $this->setFontList($data['font']??[]);
        $this->setWrapList($data['wrap']??[]);
        $this->setBackgroundList($data['background']??[]);
        $this->setColorList($data['color']??[]);
    }

    /**
     * 导出
     * @return string
     * @throws B5HttpException
     */
    public function export(): string
    {
        if (empty($this->row)) throw new B5HttpException(400, '未配置导出字段', ErrorCode::EXPORT_NO_FIELDS);
        if (empty($this->list)) throw new B5HttpException(400, '导出数据为空', ErrorCode::EXPORT_EMPTY_DATA);

        $spreadsheet = new Spreadsheet();
        $worksheet = $spreadsheet->getActiveSheet();

        //设置第一行的标题
        $index = 0;
        foreach ($this->row as $field => $name) {
            $index++;
            $worksheet->setCellValue([$index, 1], $name);
        }

        //从第二行开始插入数据
        $row_index = 1;
        foreach ($this->list as $value) {
            $row_index++;
            $column_index = 0;
            foreach ($this->row as $field => $name) {
                $column_index++;
                try {
                    $val = ArrayHelper::getValue($value, $field);
                } catch (\Exception $e) {
                    $val = $value[$field] ?? '';
                }
                $worksheet->setCellValue([$column_index, $row_index], $val);
            }
        }
        $this->afterSheet($worksheet);

        $fileName = ($this->fileName ?: md5(microtime(true) . mt_rand(1000, 9999))) . '.xlsx';
        //保存文档
        if ($this->saveFile) {
            $root = \Yii::getAlias('@root_path') . \Yii::$app->params['file_path_prefix'];
            $savePath = '/uploads/excel/' . date('Ymd');
            $path = str_replace('/', DIRECTORY_SEPARATOR, $root . $savePath);
            if (!is_dir($path)) {
                if (false === @mkdir($path, 0777, true) && !is_dir($path)) {
                    throw new B5HttpException(400, '存储文件夹创建失败：' . $path, ErrorCode::EXPORT_FAIL_DIR);
                }
            }
            try {
                $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
                $writer->save($path . DIRECTORY_SEPARATOR . $fileName);
            } catch (\Exception $exception) {
                throw new B5HttpException(500, '文档创建失败：' . $exception->getMessage(), ErrorCode::EXPORT_FAIL_FILE);
            }
            return $savePath . '/' . $fileName;
        } else {
            //直接浏览器下载
            try {
                header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
                header('Content-Disposition: attachment;filename="' . $fileName . '"');
                header('Cache-Control: max-age=0');
                $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
                $writer->save('php://output');
            } catch (\Exception $exception) {
                throw new B5HttpException(500, '文档创建失败：' . $exception->getMessage(), ErrorCode::EXPORT_FAIL_FILE);
            }
            return '';
        }
    }


    public function afterSheet(Worksheet $worksheet){
        // 设置垂直居中
        $worksheet->getStyle([1,1,count($this->row),count($this->list)+1])->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
        //设置水平居中
        $worksheet->getStyle([1,1,count($this->row),count($this->list)+1])->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);

        //换行
        foreach ($this->wrapList as $key=>$value){
            $worksheet->getStyle($key)->getAlignment()->setWrapText($value);
        }
        //设置列宽
        foreach ($this->widthList as $key=>$value){
            $worksheet->getColumnDimension($key)->setWidth($value);
        }
        //设置字体
        foreach ($this->fontList as $key=>$value){
            $worksheet->getStyle($key)->getFont()->setName($value);
        }
        //设置大小
        foreach ($this->sizeList as $key=>$value){
            $worksheet->getStyle($key)->getFont()->setSize($value);
        }
        //设置加粗
        foreach ($this->boldList as $key=>$value){
            $worksheet->getStyle($key)->getFont()->setBold($value);
        }
        //设置颜色
        foreach ($this->colorList as $key=>$value){
            $worksheet->getStyle($key)->getFont()->getColor()->setARGB($value);
        }
        //设置背景
        foreach ($this->backgroundList as $key=>$value){
            $worksheet->getStyle($key)->applyFromArray([
                'fill'=>[
                    'fillType'=>'linear',
                    'startColor'=>['rgb'=>$value],
                    'endColor'=>['argb'=>$value]
                ]
            ]);
        }
    }



    // 设置列的宽度 ['A'=>50,..]
    public function setWidthList(array $list){
        $this->widthList = array_change_key_case($list,CASE_UPPER);
    }

    // 设置加粗 ['A1:k7'=>true,..]
    public function setBoldList(array $list){
        $this->boldList = array_change_key_case($list,CASE_UPPER);
    }
    // 设置加字体 ['A1:k7'=>'宋体',..]
    public function setFontList(array $list){
        $this->fontList = array_change_key_case($list,CASE_UPPER);
    }
    // 设置文字大小 ['A1:k7'=>14,..]
    public function setSizeList(array $list){
        $this->sizeList = array_change_key_case($list,CASE_UPPER);
    }
    // 设置背景 ['A1:k7'=>'000000',..]
    public function setBackgroundList(array $list){
        $this->sizeList = array_change_key_case($list,CASE_UPPER);
    }
    // 设置换行 ['A1:k7'=>true,'A'=>true,'B3'=>true]
    public function setWrapList(array $list){
        $this->wrapList = array_change_key_case($list,CASE_UPPER);
    }
    // 设置换行 ['A1:k7'=>true,'A'=>true,'B3'=>true]
    public function setColorList(array $list){
        $this->colorList = array_change_key_case($list,CASE_UPPER);
    }

}